# -*- coding: utf-8 -*-
# @Time    : 2020/9/25 13:58
# @Author  : ergou
# @File    : get_package_path.py
# @Software: PyCharm
import sys
from ftplib import FTP  # 引入ftp模块

from application.settings import Config

# python默认的递归深度是很有限的大约900多，修改递归深度的值
sys.setrecursionlimit(1000000)
# FTP_DIR = 'E:\\pythonWebRepository\\qa-api.kcimg.cn\\application\\apps\\d_bot\\static\\ftp_dir\\'
FTP_DIR = Config.QR_DIR + 'ftp_dir/'


def is_chinese(string):
    """
    检查整个字符串是否包含中文
    :param string: 需要检查的字符串
    :return: bool
    """
    for ch in string:
        if u'\u4e00' <= ch <= u'\u9fff':
            return True

    return False


def get_num(string):
    """
    检测字符中版本号
    :param string:
    :return:
    """
    str_num = ""
    for i in filter(str.isdigit, string):
        str_num += i
    return str_num


class MyFtp:
    """
    FTP相关操作函数
    """

    def __init__(self, host, port=21):
        """
        FTP连接
        :param host: IP
        :param port: 端口
        """
        self.ftp = FTP()
        # self.ftp.encoding = "utf-8"
        self.ftp.connect(host, port)

    def login(self, username, pwd):
        """
        登录到ftp
        :param username: 用户名
        :param pwd:密码
        """
        # self.ftp.set_debuglevel(2)  # 打开调试级别2，显示详细信息
        self.ftp.encoding = 'utf-8'
        self.ftp.login(username, pwd)
        # print(self.ftp.welcome)

    def check_pt(self, text):
        """
        判断是安卓还是ios，此部分后续仍需优化~
        链接
        自定义，判断apk ipa
        :param text: 版本关键字
        :return: string
        """
        start_pathes = []
        lower_text = text.lower()
        if lower_text.isdigit():
            start_pathes = ["/App/android/", "/App/android-极速版/", "/App/ios/", "/App/ios-极速版/"]
        else:

            if "ios" in lower_text or "苹果" in lower_text:
                if "极速" in text:
                    path = "/App/ios-极速版/"
                    start_pathes.append(path)
                else:
                    path = "/App/ios/"
                    start_pathes.append(path)
                    path = "/App/ios-极速版/"
                    start_pathes.append(path)
            if "android" in lower_text or "安卓" in lower_text:
                if "极速" in text:
                    path = "/App/android-极速版/"
                    start_pathes.append(path)
                else:
                    path = "/App/android/"
                    start_pathes.append(path)
                    path = "/App/android-极速版/"
                    start_pathes.append(path)

        return start_pathes

    # @pysnooper.snoop(depth=10)
    def downloadfile(self, remotepath, name, localpath):
        """
        下载
        :param remotepath: FTP下载地址
        :param localpath: 本地保存地址
        """

        self.my_cwd(remotepath)
        f = open(localpath, 'wb')  # 打开要保存文件
        filename = 'RETR ' + name  # 保存FTP文件
        self.ftp.encoding = 'utf-8'
        self.myretrbinary(filename, f.write)  # 保存FTP上的文件
        self.ftp.set_debuglevel(0)  # 关闭调试
        f.close()  # 关闭文件

    def my_cwd(self, path):
        """
        进入目录进行encoding，修改后再还原为utf-8
        :param path: 访问ftp路径
        """
        if is_chinese(path):
            self.ftp.encoding = "GB18030"
            # 要登录的ftp目录
            self.ftp.cwd(path)
            self.ftp.encoding = "utf-8"
        else:
            self.ftp.cwd(path)

    def myretrbinary(self, filename, f):
        """
        封装下载函数，避免乱码
        :param filename: 路径
        :param f: 写入本地的路径
        """
        if is_chinese(filename):
            self.ftp.encoding = "GB18030"
            self.ftp.retrbinary(filename, f)
            self.ftp.encoding = "utf-8"
        else:
            self.ftp.retrbinary(filename, f)

    def get_path(self, text, pathes):
        """
        调用递归函数，遍历路径，获取符合条件的安装包
        :param pathes: 路径集合
        :param text: 版本关键字
        """

        path_files = []  # 声明ftp路径下包的集合
        for path in pathes:  # 进入目录，遍历路径，用来获取ftp路径下包全路径
            self.my_cwd(path)
            list_edition = self.ftp.nlst()
            if list_edition:
                for edition_dir in list_edition:  # 遍历版本文件夹
                    if get_num(text) in get_num(edition_dir):  # 匹配版本关键字
                        edition_dir_path = path + edition_dir + '/'
                        path_files.append(edition_dir_path)
            list_edition.clear()
        if path_files:  # 版本文件夹下有内容则调用递归方法获取最新包
            path_files_package = []  # 声明返回符合条件安装包的集合
            return self.get_package_recursion(path_files, text, path, path_files_package, 2)
        return []

    def get_package_recursion(self, pathes, text, root_dir, path_files_package, flag):
        """
        获取符合条件的安装包的递归方法
        :param flag: 是否指定目录标识
        :param pathes: 版本路径集合
        :param text: 版本关键字
        :param root_dir: 版本目录
        :param path_files_package: 包全路径集合
        :return: list
        """
        # 声明ftp路径下包的集合
        clear_path_files = []  # 清空返回文件包路径
        if flag == 1 and ('.apk' in pathes[-1] or '.ipa' in pathes[-1]):
            clear_path_files.append({str(root_dir): pathes[-1]})  # 获取最后一个安装包
        else:
            for path in pathes:
                if flag == 0 and path == text:
                    clear_path_files.append({str(root_dir): path})
                elif flag == 2 and (get_num(text) in get_num(path)) and ('.apk' in path or '.ipa' in path):
                    if clear_path_files:  # 获取最后一个安装包
                        clear_path_files.clear()
                    clear_path_files.append({str(root_dir): path})
                else:  # 非apk,ipa安装包
                    try:
                        self.my_cwd(path)
                        list_edition = self.ftp.nlst()
                        if list_edition:
                            new_path = str(self.ftp.pwd()).encode('iso-8859-1').decode('gbk') + '/'
                            self.get_package_recursion(list_edition, text, new_path, path_files_package, flag)
                    except:
                        print('非文件夹路径访问异常！')
                        continue
        if clear_path_files:
            path_files_package.append(clear_path_files)
        return path_files_package

    def close(self):
        """
        退出ftp连接
        """
        self.ftp.set_debuglevel(0)  # 关闭调试
        self.ftp.quit()

    def run(self, text):
        """
        遍历符合关键字的安装包集合，进行下载
        :param text: 版本关键字
        :return: 本地安装包全路径集合
        """

        file_list = []
        # str(text).encode('utf-8')
        if text.endswith('.apk') or text.endswith('.ipa'):
            file_list = self.fixed_path("/App/custom/", text)
        elif "链接" in text:
            file_list = self.fixed_path("/App/testurl/", text)
        # 判断版本关键字是否是三位数字
        elif len(get_num(text)) >= 3:
            pathes = self.check_pt(text)  # 判断是安卓还是ios
            file_list = self.get_path(text, pathes)
        if file_list:
            local_files = []
            for i in file_list:
                name = ''.join(i[0].values())
                self.downloadfile(''.join(i[0].keys()), name, FTP_DIR + name)
                local_files.append(FTP_DIR + name)
            self.close()
            return local_files
        return []

    def fixed_path(self, path, text):
        """
        指定测试链接路径"/App/testurl/"或者指定完整包名路径"/App/custom/"
        :param path: 指定路径
        :param text: 关键字
        :return: list
        """
        self.my_cwd(path)
        list_edition = self.ftp.nlst()
        if list_edition:
            if path == "/App/custom/":
                return self.get_package_recursion(list_edition, text, path, [], 0)
            if path == "/App/testurl/":
                return self.get_package_recursion(list_edition, text, path, [], 1)
        return []


if __name__ == '__main__':
    ftp = MyFtp('192.168.2.250')
    ftp.encoding = "utf-8"
    ftp.login('dev-app', '360che.com')
    print(ftp.run("app_1.6.2_15_baidu_release.apk"))
    # print(ftp.run("测试链接无缓存版本.ipa"))
